package com.tanhua.server.service;

import cn.hutool.core.collection.CollUtil;
import com.tanhua.autoconfig.template.OssTemplate;
import com.tanhua.commons.utils.Constants;
import com.tanhua.dubbo.api.CommentsApi;
import com.tanhua.dubbo.api.MovementApi;
import com.tanhua.dubbo.api.UserInfoApi;
import com.tanhua.model.domain.UserInfo;
import com.tanhua.model.enums.CommentType;
import com.tanhua.model.mongo.Comment;
import com.tanhua.model.mongo.Movement;
import com.tanhua.model.vo.ErrorResult;
import com.tanhua.model.vo.MovementsVo;
import com.tanhua.model.vo.PageResult;
import com.tanhua.server.exception.BusinessException;
import com.tanhua.server.interceptor.UserHolder;
import org.apache.dubbo.config.annotation.DubboReference;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class MovementService {

    @Autowired
    private OssTemplate ossTemplate;

    @DubboReference
    private MovementApi movementApi;

    @DubboReference
    private UserInfoApi userInfoApi;

    @DubboReference
    private CommentsApi commentsApi;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;


    /*圈子-发布动态*/
    public void publishMovements(Movement movement, MultipartFile[] imageContent) throws IOException {
        //获取当前用户ID
        Long userId = UserHolder.getUserId();
        //判断发布的文字内容是否存在
        if (StringUtils.isEmpty(movement.getTextContent())) {
            //不存在则抛出异常(动态内容为空)
            throw new BusinessException(ErrorResult.contentError());
        }
        //将文件内容上传至阿里云
        List<String> medias = new ArrayList<>();
        for (MultipartFile multipartFile : imageContent) {
            String upload = ossTemplate.upload(multipartFile.getOriginalFilename(), multipartFile.getInputStream());
            medias.add(upload);
        }
        //将媒体数据，图片或小视频的url封装到Movement对象
        movement.setUserId(userId);
        movement.setMedias(medias);
        //调用API进行动态的发布
        movementApi.publishMovement(movement);
    }

    /*圈子-查询我的动态*/
    public PageResult findByUserId(Long userId, Integer page, Integer pagesize) {
        //根据用户id，调用API查询个人动态
        PageResult pr = movementApi.findByUserId(userId, page, pagesize);
        //获取PageResult中的item列表对象
        List<Movement> items = (List<Movement>) pr.getItems();
        //判断item是否为空
        if (items == null) {
            return pr;
        }
        //循环数据列表，将Movement构建成Vo对象,并存入集合
        UserInfo userInfo = userInfoApi.findById(userId);
        List<MovementsVo> vos = new ArrayList<>();
        for (Movement item : items) {
            MovementsVo vo = MovementsVo.init(userInfo, item);
            vos.add(vo);
        }
        //构建返回值
        pr.setItems(vos);
        return pr;
    }

    /*圈子-好友动态*/
    public PageResult findFriendMovements(Integer page, Integer pagesize) {
        //获取当前用户id
        Long userId = UserHolder.getUserId();
        //查询好友时间线表
        List<Movement> items = movementApi.findFriendMovements(userId, page, pagesize);
        return getPageResult(page, pagesize, items);
    }


    /*圈子-推荐动态*/
    public PageResult findRecommendMovements(Integer page, Integer pagesize) {
        //从redis中获取推荐数据
        String redisKey = Constants.MOVEMENTS_RECOMMEND + UserHolder.getUserId();
        String redisValue = redisTemplate.opsForValue().get(redisKey);
        //判断推荐数据是否存在
        //构建一个空的list集合
        List<Movement> list = Collections.EMPTY_LIST;
        if (StringUtils.isEmpty(redisValue)) {
            //返回ture表示数据不存在，则调用api随机生成
            list = movementApi.randomMovements(pagesize);
        } else {
            //存在则对这些数据进行处理
            String[] split = redisValue.split(",");
            //判断当前页的起始条数是否大于总条数
            if (split.length < (page - 1) * pagesize) {
                return new PageResult();
            }
            List<Long> pids = Arrays.stream(split).skip((page - 1) * pagesize).limit(pagesize)
                    .map(e -> Long.valueOf(e))
                    .collect(Collectors.toList());
            //调用api通过pid查询动态数据
            list = movementApi.findMovementsByPids(pids);
        }
        return getPageResult(page, pagesize, list);
    }


    public PageResult getPageResult(Integer page, Integer pagesize, List<Movement> items) {
        //判断items是否为空
        if (CollUtil.isEmpty(items)) {
            return new PageResult();
        }
        //不为空则提取列表里的所有好友用户的id，存入list集合
        List<Long> ids = CollUtil.getFieldValues(items, "userId", Long.class);
        //查询好友的详细信息
        Map<Long, UserInfo> map = userInfoApi.findByIds(ids, null);
        //循环数据列表,将Movement构建成Vo对象,并存入集合
        List<MovementsVo> vos = new ArrayList<>();
        for (Movement item : items) {
            UserInfo userInfo = map.get(item.getUserId());
            if (userInfo!=null) {
                MovementsVo vo = MovementsVo.init(userInfo, item);
                //判断hashKey是否存在c
                String key = Constants.MOVEMENTS_INTERACT_KEY + item.getId().toHexString();
                String hashKey1 = Constants.MOVEMENT_LIKE_HASHKEY + UserHolder.getUserId();
                String hashKey2 = Constants.MOVEMENT_LOVE_HASHKEY + UserHolder.getUserId();
                if(redisTemplate.opsForHash().hasKey(key,hashKey1)) {
                    vo.setHasLiked(1);
                }
                if (redisTemplate.opsForHash().hasKey(key,hashKey2)){
                    vo.setHasLoved(1);
                }
                vos.add(vo);
            }
        }
        //构建返回值
        return new PageResult(page, pagesize, 0L, vos);
    }

    /*圈子-单条动态*/
    public MovementsVo findMovementById(String movementId) {
        //调用api查询动态详情
        Movement movement = movementApi.findById(movementId);
        //判断movement是否为空
        if (movement == null) {
            return null;
        } else {
            Long userId = movement.getUserId();
            //调用api查询用户详情
            UserInfo userInfo = userInfoApi.findById(userId);
            //构建movementVo
            return MovementsVo.init(userInfo,movement);
        }

    }

    /*圈子-动态点赞*/
    public Integer like(String movementId) {
        //获取当前用户id
        Long userId = UserHolder.getUserId();
        //查询该用户是否已经点赞
        Boolean result=commentsApi.hasComment(userId,movementId,CommentType.LIKE);
        //已点赞则抛出异常
        if (result){
            throw new BusinessException(ErrorResult.likeError());
        }
        //构造Comment
        Comment comment=new Comment();
        comment.setPublishId(new ObjectId(movementId));
        comment.setCommentType(CommentType.LIKE.getType());
        comment.setUserId(userId);
        comment.setCreated(System.currentTimeMillis());
        //添加点赞信息
        Integer likeCount = commentsApi.save(comment);
        //将点赞状态存入redis
        String key = Constants.MOVEMENTS_INTERACT_KEY + movementId;
        String hashKey = Constants.MOVEMENT_LIKE_HASHKEY + UserHolder.getUserId();
        redisTemplate.opsForHash().put(key,hashKey,"1");
        return likeCount;
    }

    /*圈子-取消点赞*/
    public Integer dislike(String movementId) {
        //获取当前用户id
        Long userId = UserHolder.getUserId();
        //查询该用户是否已经点赞
        Boolean result=commentsApi.hasComment(userId,movementId,CommentType.LIKE);
        //没有点赞则抛出异常
        if (!result){
            throw new BusinessException(ErrorResult.disLikeError());
        }
        //构造Comment
        Comment comment=new Comment();
        comment.setPublishId(new ObjectId(movementId));
        comment.setCommentType(CommentType.LIKE.getType());
        comment.setUserId(userId);
        comment.setCreated(System.currentTimeMillis());
        //删除点赞信息
        Integer likeCount = commentsApi.delete(comment);
        //在redis中删除点赞状态
        String key = Constants.MOVEMENTS_INTERACT_KEY + movementId;
        String hashKey = Constants.MOVEMENT_LIKE_HASHKEY + UserHolder.getUserId();
        redisTemplate.opsForHash().delete(key,hashKey);
        return likeCount;
    }

    /*圈子-动态喜欢*/
    public Integer love(String movementId) {
        //获取当前用户id
        Long userId = UserHolder.getUserId();
        //查询该用户是否已经喜欢
        Boolean result=commentsApi.hasComment(userId,movementId,CommentType.LOVE);
        //已喜欢则抛出异常
        if (result){
            throw new BusinessException(ErrorResult.loveError());
        }
        //构造Comment
        Comment comment=new Comment();
        comment.setPublishId(new ObjectId(movementId));
        comment.setCommentType(CommentType.LOVE.getType());
        comment.setUserId(userId);
        comment.setCreated(System.currentTimeMillis());
        //添加喜欢信息
        Integer loveCount = commentsApi.save(comment);
        //将喜欢状态存入redis
        String key = Constants.MOVEMENTS_INTERACT_KEY + movementId;
        String hashKey = Constants.MOVEMENT_LOVE_HASHKEY + UserHolder.getUserId();
        redisTemplate.opsForHash().put(key,hashKey,"1");
        return loveCount;
    }

    /*圈子-取消喜欢*/
    public Integer unlove(String movementId) {
        //获取当前用户id
        Long userId = UserHolder.getUserId();
        //查询该用户是否已经喜欢
        Boolean result=commentsApi.hasComment(userId,movementId,CommentType.LOVE);
        //没有喜欢则抛出异常
        if (!result){
            throw new BusinessException(ErrorResult.disloveError());
        }
        //构造Comment
        Comment comment=new Comment();
        comment.setPublishId(new ObjectId(movementId));
        comment.setCommentType(CommentType.LOVE.getType());
        comment.setUserId(userId);
        comment.setCreated(System.currentTimeMillis());
        //删除点赞信息
        Integer loveCount = commentsApi.delete(comment);
        //在redis中删除喜欢状态
        String key = Constants.MOVEMENTS_INTERACT_KEY + movementId;
        String hashKey = Constants.MOVEMENT_LOVE_HASHKEY + UserHolder.getUserId();
        redisTemplate.opsForHash().delete(key,hashKey);
        return loveCount;
    }
}



